// 支付工具模块 - 微信支付和支付宝支付
const crypto = require('crypto');
const axios = require('axios');
const moment = require('moment');

// ========== 微信支付配置 ==========
const WECHAT_PAY_CONFIG = {
  appId: process.env.WECHAT_PAY_APPID || '',
  mchId: process.env.WECHAT_PAY_MCHID || '', // 商户号
  apiKey: process.env.WECHAT_PAY_API_KEY || '', // API密钥
  notifyUrl: process.env.WECHAT_PAY_NOTIFY_URL || 'http://localhost:5000/api/payments/wechat/notify',
  // 微信支付证书路径（可选，用于退款等高级功能）
  certPath: process.env.WECHAT_PAY_CERT_PATH || '',
  keyPath: process.env.WECHAT_PAY_KEY_PATH || ''
};

// ========== 支付宝支付配置 ==========
const ALIPAY_CONFIG = {
  appId: process.env.ALIPAY_APPID || '',
  privateKey: process.env.ALIPAY_PRIVATE_KEY || '', // 应用私钥
  alipayPublicKey: process.env.ALIPAY_PUBLIC_KEY || '', // 支付宝公钥
  notifyUrl: process.env.ALIPAY_NOTIFY_URL || 'http://localhost:5000/api/payments/alipay/notify',
  returnUrl: process.env.ALIPAY_RETURN_URL || 'http://localhost:5180/payment/result',
  gateway: process.env.ALIPAY_GATEWAY || 'https://openapi.alipay.com/gateway.do',
  // 是否为沙箱环境
  isSandbox: process.env.ALIPAY_SANDBOX === 'true'
};

// 生成随机字符串
function generateNonceStr(length = 32) {
  return crypto.randomBytes(Math.ceil(length / 2))
    .toString('hex')
    .slice(0, length);
}

// ========== 微信支付相关函数 ==========

/**
 * 创建微信支付订单（统一下单）
 * @param {Object} params - 支付参数
 * @param {string} params.orderId - 订单ID
 * @param {string} params.description - 商品描述
 * @param {number} params.amount - 金额（单位：分）
 * @param {string} params.openid - 用户openid（JSAPI支付必需）
 * @param {string} params.clientIp - 用户IP地址
 * @returns {Promise<Object>} 返回支付参数（前端调起支付所需）
 */
async function createWechatPayment(params) {
  const { orderId, description, amount, openid, clientIp } = params;

  // 详细的配置检查
  const missingConfigs = [];
  if (!WECHAT_PAY_CONFIG.appId) missingConfigs.push('WECHAT_PAY_APPID');
  if (!WECHAT_PAY_CONFIG.mchId) missingConfigs.push('WECHAT_PAY_MCHID');
  if (!WECHAT_PAY_CONFIG.apiKey) missingConfigs.push('WECHAT_PAY_API_KEY');

  if (missingConfigs.length > 0) {
    throw new Error(`微信支付配置不完整，缺少以下环境变量：${missingConfigs.join(', ')}。请参考 backend/PAYMENT_CONFIG.md 配置指南。`);
  }

  const nonceStr = generateNonceStr();
  const outTradeNo = `ORDER_${orderId}_${Date.now()}`;
  const timeStamp = Math.floor(Date.now() / 1000).toString();

  // 构建统一下单参数
  const unifiedOrderParams = {
    appid: WECHAT_PAY_CONFIG.appId,
    mch_id: WECHAT_PAY_CONFIG.mchId,
    nonce_str: nonceStr,
    body: description || '校园快递代拿服务',
    out_trade_no: outTradeNo,
    total_fee: Math.round(amount * 100), // 转换为分
    spbill_create_ip: clientIp || '127.0.0.1',
    notify_url: WECHAT_PAY_CONFIG.notifyUrl,
    trade_type: openid ? 'JSAPI' : 'MWEB', // JSAPI=公众号支付，MWEB=H5支付
    ...(openid ? { openid } : {})
  };

  // 生成签名
  const sign = generateWechatSign(unifiedOrderParams, WECHAT_PAY_CONFIG.apiKey);
  unifiedOrderParams.sign = sign;

  // 转换为XML格式
  const xml = paramsToXml(unifiedOrderParams);

  try {
    // 调用微信统一下单API
    const response = await axios.post('https://api.mch.weixin.qq.com/pay/unifiedorder', xml, {
      headers: {
        'Content-Type': 'application/xml'
      }
    });

    // 解析XML响应
    const result = xmlToParams(response.data);

    if (result.return_code === 'SUCCESS' && result.result_code === 'SUCCESS') {
      // 返回前端需要的支付参数
      if (openid) {
        // JSAPI支付参数
        const payParams = {
          appId: WECHAT_PAY_CONFIG.appId,
          timeStamp: timeStamp,
          nonceStr: generateNonceStr(),
          package: `prepay_id=${result.prepay_id}`,
          signType: 'MD5'
        };
        payParams.paySign = generateWechatSign(payParams, WECHAT_PAY_CONFIG.apiKey);

        return {
          success: true,
          paymentType: 'wechat_jsapi',
          params: payParams,
          outTradeNo: outTradeNo
        };
      } else {
        // H5支付（返回支付URL）
        return {
          success: true,
          paymentType: 'wechat_h5',
          paymentUrl: result.mweb_url,
          outTradeNo: outTradeNo
        };
      }
    } else {
      throw new Error(result.err_code_des || result.return_msg || '微信支付下单失败');
    }
  } catch (error) {
    console.error('❌ 微信支付下单失败:', error);
    throw new Error('微信支付下单失败: ' + (error.message || '未知错误'));
  }
}

/**
 * 验证微信支付回调签名
 */
function verifyWechatSign(params, apiKey) {
  const { sign, ...otherParams } = params;
  const calculatedSign = generateWechatSign(otherParams, apiKey);
  return calculatedSign === sign;
}

/**
 * 生成微信支付签名（MD5）
 */
function generateWechatSign(params, apiKey) {
  // 1. 过滤空值并排序
  const sortedKeys = Object.keys(params)
    .filter(key => params[key] !== '' && params[key] !== null && params[key] !== undefined)
    .sort();

  // 2. 拼接字符串
  const stringA = sortedKeys.map(key => `${key}=${params[key]}`).join('&');
  const stringSignTemp = `${stringA}&key=${apiKey}`;

  // 3. MD5加密并转大写
  return crypto.createHash('md5').update(stringSignTemp, 'utf8').digest('hex').toUpperCase();
}

// ========== 支付宝支付相关函数 ==========

/**
 * 创建支付宝支付订单（统一下单）
 * @param {Object} params - 支付参数
 * @param {string} params.orderId - 订单ID
 * @param {string} params.description - 商品描述
 * @param {number} params.amount - 金额（单位：元）
 * @returns {Promise<Object>} 返回支付表单HTML或支付URL
 */
async function createAlipayPayment(params) {
  const { orderId, description, amount } = params;

  // 详细的配置检查
  const missingConfigs = [];
  if (!ALIPAY_CONFIG.appId) missingConfigs.push('ALIPAY_APPID');
  if (!ALIPAY_CONFIG.privateKey) missingConfigs.push('ALIPAY_PRIVATE_KEY');

  if (missingConfigs.length > 0) {
    throw new Error(`支付宝支付配置不完整，缺少以下环境变量：${missingConfigs.join(', ')}。请参考 backend/PAYMENT_CONFIG.md 配置指南。`);
  }

  const outTradeNo = `ORDER_${orderId}_${Date.now()}`;
  const timestamp = moment().format('YYYY-MM-DD HH:mm:ss');

  // 构建请求参数
  const bizContent = {
    out_trade_no: outTradeNo,
    product_code: 'QUICK_WAP_WAY', // 手机网站支付
    total_amount: amount.toFixed(2),
    subject: description || '校园快递代拿服务'
  };

  const alipayParams = {
    app_id: ALIPAY_CONFIG.appId,
    method: 'alipay.trade.wap.pay',
    format: 'JSON',
    charset: 'utf-8',
    sign_type: 'RSA2',
    timestamp: timestamp,
    version: '1.0',
    biz_content: JSON.stringify(bizContent),
    notify_url: ALIPAY_CONFIG.notifyUrl,
    return_url: ALIPAY_CONFIG.returnUrl
  };

  // 生成签名
  const sign = generateAlipaySign(alipayParams, ALIPAY_CONFIG.privateKey);
  alipayParams.sign = sign;

  // 构建支付URL
  const paymentUrl = `${ALIPAY_CONFIG.gateway}?${paramsToQueryString(alipayParams)}`;

  return {
    success: true,
    paymentType: 'alipay_h5',
    paymentUrl: paymentUrl,
    outTradeNo: outTradeNo,
    // 如果是PC网站，可以返回表单HTML
    formHtml: generateAlipayForm(alipayParams)
  };
}

/**
 * 验证支付宝回调签名
 */
function verifyAlipaySign(params, alipayPublicKey) {
  if (!alipayPublicKey) {
    console.warn('支付宝公钥未配置，跳过签名验证');
    return false;
  }

  const { sign, sign_type, ...otherParams } = params;

  // 构建待签名字符串
  const sortedKeys = Object.keys(otherParams)
    .filter(key => otherParams[key] !== '' && otherParams[key] !== null && key !== 'sign')
    .sort();

  const signContent = sortedKeys
    .map(key => `${key}=${otherParams[key]}`)
    .join('&');

  // 格式化公钥
  let formattedPublicKey = alipayPublicKey;
  if (!formattedPublicKey.includes('BEGIN')) {
    formattedPublicKey = `-----BEGIN PUBLIC KEY-----\n${formattedPublicKey.replace(/\s+/g, '')}\n-----END PUBLIC KEY-----`;
  }
  formattedPublicKey = formattedPublicKey.replace(/\\n/g, '\n');

  // 使用支付宝公钥验证签名
  const verify = crypto.createVerify('RSA-SHA256');
  verify.update(signContent, 'utf8');

  try {
    return verify.verify(formattedPublicKey, sign, 'base64');
  } catch (error) {
    console.error('支付宝签名验证失败:', error);
    return false;
  }
}

/**
 * 生成支付宝签名（RSA2）
 */
function generateAlipaySign(params, privateKey) {
  if (!privateKey) {
    throw new Error('支付宝私钥未配置');
  }

  // 1. 过滤空值并排序
  const sortedKeys = Object.keys(params)
    .filter(key => params[key] !== '' && params[key] !== null && params[key] !== undefined && key !== 'sign')
    .sort();

  // 2. 拼接字符串
  const signContent = sortedKeys
    .map(key => `${key}=${params[key]}`)
    .join('&');

  // 3. RSA2签名
  const sign = crypto.createSign('RSA-SHA256');
  sign.update(signContent, 'utf8');

  // 注意：私钥格式需要是 PEM 格式
  let formattedPrivateKey = privateKey;
  if (!formattedPrivateKey.includes('BEGIN')) {
    // 如果没有BEGIN标记，尝试格式化
    formattedPrivateKey = `-----BEGIN RSA PRIVATE KEY-----\n${formattedPrivateKey.replace(/\s+/g, '')}\n-----END RSA PRIVATE KEY-----`;
  }
  // 处理环境变量中的 \n
  formattedPrivateKey = formattedPrivateKey.replace(/\\n/g, '\n');

  try {
    return sign.sign(formattedPrivateKey, 'base64');
  } catch (error) {
    console.error('支付宝签名失败:', error);
    throw new Error('支付宝签名生成失败: ' + error.message);
  }
}

// ========== 工具函数 ==========

/**
 * 对象转XML（简单实现）
 */
function paramsToXml(params) {
  const xmlParts = ['<xml>'];
  for (const [key, value] of Object.entries(params)) {
    xmlParts.push(`<${key}><![CDATA[${value}]]></${key}>`);
  }
  xmlParts.push('</xml>');
  return xmlParts.join('');
}

/**
 * XML转对象（简单实现）
 */
function xmlToParams(xml) {
  const params = {};
  // 匹配 CDATA 格式
  const cdataRegex = /<(\w+)><!\[CDATA\[(.*?)\]\]><\/\1>/g;
  let match;
  while ((match = cdataRegex.exec(xml)) !== null) {
    params[match[1]] = match[2];
  }
  // 匹配普通格式（如果没有CDATA）
  if (Object.keys(params).length === 0) {
    const normalRegex = /<(\w+)>(.*?)<\/\1>/g;
    while ((match = normalRegex.exec(xml)) !== null) {
      params[match[1]] = match[2];
    }
  }
  return params;
}

/**
 * 对象转查询字符串
 */
function paramsToQueryString(params) {
  return Object.keys(params)
    .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
    .join('&');
}

/**
 * 生成支付宝支付表单HTML
 */
function generateAlipayForm(params) {
  const formHtml = `
        <form id="alipay-form" action="${ALIPAY_CONFIG.gateway}" method="POST">
            ${Object.keys(params).map(key => `<input type="hidden" name="${key}" value="${params[key]}" />`).join('\n')}
        </form>
        <script>document.getElementById('alipay-form').submit();</script>
    `;
  return formHtml;
}

module.exports = {
  createWechatPayment,
  createAlipayPayment,
  verifyWechatSign,
  verifyAlipaySign,
  generateNonceStr,
  paramsToXml,
  xmlToParams,
  WECHAT_PAY_CONFIG,
  ALIPAY_CONFIG
};

